import { eventBusType } from "./types";

export function initEventBus<T,K extends [string, ...any[]]>(): eventBusType<T,K> {
    const bus: eventBusType<T,K> = Object.create(null);

    Reflect.defineProperty(bus, 'store', { value: Object.create(null) });
    Reflect.defineProperty(bus, 'eventMap', { value: new Map() });

    Reflect.defineProperty(bus, 'on', {
        value(eventName: string, callback: Function) {
            let eventMap = bus.eventMap;
            if (eventMap.has(eventName)) {
                eventMap.get(eventName)!.add(callback);
                return;
            }
            eventMap.set(eventName, new Set([callback]));
        }
    });

    Reflect.defineProperty(bus, 'off', {
        value(eventName: string, callback: Function) {
            let eventMap = bus.eventMap;
            if (eventMap.has(eventName)) {
                let callbackListSet = eventMap.get(eventName)!;
                callbackListSet.delete(callback);
                callbackListSet.size === 0 && eventMap.delete(eventName);
                return;
            }
            console.error('找不到目标事件，无法卸载回调函数！')
        }
    });

    Reflect.defineProperty(bus, 'emmit', {
        value(eventName: string, ...args: any[]) {
            let eventMap = bus.eventMap;
            if (!eventMap.has(eventName)) return console.error('找不到目标事件，无法触发回调函数！');

            eventMap.get(eventName)!.forEach(cb => {
                cb.apply(bus, args)
            });
        }
    });

    Reflect.defineProperty(bus, 'once', {
        value(eventName: string, callback: Function) {
            let eventMap = bus.eventMap;
            if (!eventMap.has(eventName)) {
                eventMap.set(eventName, new Set())
            }
            eventMap.get(eventName)!.add(function oneFn(...args: any[]) {
                callback.apply(bus, args);
                bus.off(eventName, oneFn);
            })
        }
    });

    return bus;
};